package com.motu.monstercity.server.game.web;

import com.googlecode.protobuf.format.JsonFormat;
import com.motu.monstercity.module.common.network.DataDecoded;
import com.motu.monstercity.module.common.network.DataEncoded;
import com.motu.monstercity.module.common.network.ResponseUtils;
import com.motu.monstercity.module.common.redis.RedisKey;
import com.motu.monstercity.module.common.servermanager.ServerInfo;
import com.motu.monstercity.module.common.servermanager.ServerManager;
import com.motu.monstercity.module.common.utility.ServerParam;
import com.motu.monstercity.protocol.CmdEnum.EnumCmdID;
import com.motu.monstercity.protocol.CommonHttp.PBRoleInfo;
import com.motu.monstercity.protocol.CommonHttp.PBServerInfo;
import com.motu.monstercity.protocol.CsHttp.*;
import com.motu.vertx.module.utility.base.LoginTypeEnum;
import com.motu.vertx.module.utility.base.ServerConfig;
import com.motu.vertx.module.utility.commondata.CommonDataManager;
import com.motu.vertx.module.utility.login.LoginManager;
import com.motu.vertx.module.utility.main.MainService;
import com.motu.vertx.module.utility.model.EntityManager;
import com.motu.vertx.module.utility.monitor.LoginMonitorManager;
import com.motu.vertx.module.utility.monitor.MonitorManager;
import com.motu.vertx.module.utility.mysql.MysqlClient;
import com.motu.vertx.module.utility.mysql.MysqlTool;
import com.motu.vertx.module.utility.redis.RedisTools;
import com.motu.vertx.module.utility.toolset.ErrorWord;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import com.motu.vertx.module.utility.webtool.BaseWebHandler;
import io.vertx.core.*;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.CorsHandler;
import io.vertx.ext.web.handler.SessionHandler;
import io.vertx.ext.web.sstore.LocalSessionStore;
import io.vertx.redis.client.RedisAPI;
import io.vertx.redis.client.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class WebVerticle extends AbstractVerticle {

    private static final Logger logger = LoggerFactory.getLogger(WebVerticle.class);
    public static WebClient webClient;// http客户端

    @Override
    public void start(Promise<Void> future) {
        // 创建http客户端
        webClient = WebClient.create(vertx, new WebClientOptions().setKeepAlive(true));

        // 启动web服务
        startWeb(httpServer -> {
            if (httpServer.failed()) {
                logger.error("### startWeb fail !!!");
                httpServer.cause().printStackTrace();
                future.fail(httpServer.cause());
            } else {
                logger.info(">>>>>>>>>>>>>>> web server listen port " + httpServer.result().actualPort());
                ProtocolmonitorHandler.init(ServerConfig.getAppConfig());
                future.complete();
            }
        });

    }

    /**
     * 启动web服务
     */
    public void startWeb(Handler<AsyncResult<HttpServer>> httpServer) {
        logger.info(">>>>>>>>>>>>>>> startWeb");

        Router router = Router.router(vertx);
        router.route("/").handler(routingContext -> {
            routingContext.response().setStatusCode(200).setStatusMessage("OK").end("Web service is running!!");
        });

        /**
         * 注意：
         * 定义了BodyHandler.create之后，只能通过同步方式直接获取body内容，例如context.body().asString()，否则要用routingContext.request().bodyHandler(buffer -> {})获取body内容
         * 参数设置false是为了解决服务器上生成file-uploads漏洞问题，原因是创建websocket或者http连接时，使用的BodyHandler.create方法默认允许生成上传目录，只要把上传目录的参数置否就可以了
         */
        router.route().handler(BodyHandler.create(false));
        SessionHandler sessionHandler = SessionHandler.create(LocalSessionStore.create(vertx));
        sessionHandler.setSessionTimeout(24*3600*1000*7);//设置session的超时时间
        router.route().handler(sessionHandler);
        Set<String> allowHeaders = new HashSet<>();
        allowHeaders.add("x-requested-with");
        allowHeaders.add("Access-Control-Allow-Origin");
        allowHeaders.add("origin");
        allowHeaders.add("Content-Type");
        allowHeaders.add("accept");
        router.route().handler(CorsHandler.create("*").allowedHeaders(allowHeaders).allowedMethod(HttpMethod.POST));

        // web后台相关业务
        router.post("/admin/*").handler(this::doLogic);

        // 启动http服务
        int httpPort = config().getInteger("http-port");// 端口
        String hostName = config().getString("host-name");
        vertx.createHttpServer().requestHandler(router).listen(httpPort, hostName, httpServer::handle);
    }

    /***
     * 处理登陆相关逻辑
     * @param context
     */
    private void doLogic(RoutingContext context) {
        RouterManager.handler(context, webClient);
    }
}
